package com.patchmanage.back.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.patchmanage.back.annotation.LoginValidate;
import com.patchmanage.back.annotation.OperLog;
import com.patchmanage.back.dto.InventoryDto;
import com.patchmanage.back.entity.DepartmentGroup;
import com.patchmanage.back.entity.Inventory;
import com.patchmanage.back.exception.SystemException;
import com.patchmanage.back.result.CodeMsg;
import com.patchmanage.back.result.Result;
import com.patchmanage.back.service.IDepartmentGroupService;
import com.patchmanage.back.service.IInventoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;

/**
 * <p>
 * 资产 控制器
 * </p>
 *
 * @author huizhao
 * @since 2021-03-20
 */
@Api(value = " 资产 controller", tags = {"资产 Api"})
@RestController
@RequestMapping("/back/inventory")
public class InventoryController {

    @Autowired
    public IInventoryService inventoryService;

    @Autowired
    public IDepartmentGroupService departmentGroupService;

    /**
     * 获取资产列表
     *
     * @param dict
     * @return
     */
    @ApiOperation(value = "分页获取资产列表接口", notes = "获取资产列表接口")
    @RequestMapping(value = "list", method = RequestMethod.POST)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = false, dataType = "Integer", paramType = "body"),
            @ApiImplicitParam(name = "name", value = "name", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "owner", value = "owner", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "os", value = "os", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "ip", value = "ip", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "safeLv", value = "safeLv", required = false, dataType = "Integer", paramType = "body"),
            @ApiImplicitParam(name = "isTest", value = "isTest", required = false, dataType = "Integer", paramType = "body"),
            @ApiImplicitParam(name = "isAvailable", value = "isAvailable", required = false, dataType = "Integer", paramType = "body"),
            @ApiImplicitParam(name = "disTime", value = "disTime", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "departmentName", value = "departmentName", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "groupId", value = "groupId", required = false, dataType = "Integer", paramType = "body"),
            @ApiImplicitParam(name = "search", value = "search", required = false, dataType = "String", paramType = "body"),
            @ApiImplicitParam(name = "pageNo", value = "pageNo", required = true, dataType = "Integer", paramType = "body"),
            @ApiImplicitParam(name = "pageSize", value = "pageSize", required = true, dataType = "Integer", paramType = "body")
    })
    public Result<IPage<InventoryDto>> list(@ApiIgnore @RequestBody Dict dict) {
        Integer pageNo = dict.getInt("pageNo");
        Integer pageSize = dict.getInt("pageSize");
        IPage<InventoryDto> page = new Page(pageNo, pageSize);


        String disTimeStr = dict.getStr("disTime");
        Date disTime = null;
        if(StrUtil.isNotBlank(disTimeStr)){
            disTimeStr = disTimeStr.replace("T"," ");
            disTimeStr = disTimeStr.replace("Z","");
            disTime = DateUtil.parseDate(disTimeStr);
        }

        Set<Integer> groupIdSet = null;
        if(dict.getInt("groupId") != null){
            Set<Integer> groupIdsSet = new HashSet<>();
            departmentGroupService.recursiveGetIds(dict.getInt("groupId"),groupIdsSet);
            List<Integer> result = new ArrayList<>(groupIdsSet);
            dict.set("groupId",result);
        }


        String ip = dict.getStr("ip");
        if(disTime != null){
            Date disStatTime = DateUtil.beginOfDay(disTime);
            Date disEndTime = DateUtil.endOfDay(disTime);
        }
        if(StrUtil.isNotBlank(ip)){
           if(ip.indexOf("-") != -1){
               String[] ipArray = ip.split("-");
               String ipStart = ipArray[0];
               String ipEnd = ipArray[1];
               //INET_ATON('ip') between INET_ATON(#{map.ipStart}) and INET_ATON(#{map.ipEnd})
               dict.put("ipSql","INET_ATON(ip) between INET_ATON('"+ipStart+"') and INET_ATON('"+ipEnd+"')");
               dict.remove("ip");
           }
        }
        //INET_ATON
        return Result.success(inventoryService.listPageEx(page, dict));
    }

    /**
     * 获取资产信息
     * @param dict
     * @return
     */
    @ApiOperation(value = "获取资产信息接口", notes = "获取资产信息接口")
    @RequestMapping(value = "getById", method = RequestMethod.POST)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Integer", paramType = "body"),
    })
    @LoginValidate
    public Result<Inventory> getById(@ApiIgnore @RequestBody Dict dict) {
        return Result.success(inventoryService.getById(dict.getInt("id")));
    }


    /**
     * 新增或修改资产信息
     * @param inventory
     * @return
     */
    @ApiOperation(value = "新增或修改资产信息接口", notes = "新增或修改资产信息接口")
    @RequestMapping(value = "saveOrUpdate", method = RequestMethod.POST)
    @LoginValidate
    @OperLog(operModul="资产",operDesc="新增或修改")
    public Result<Boolean> saveOrUpdate(@RequestBody Inventory inventory) {
        if(inventory.getGroupId() != null){
            if(inventory.getIsAvailable() == null ||  inventory.getIsAvailable() == 0){
                throw new SystemException(CodeMsg.INVENTORY_SETGROUP_ERROR);
            }
            DepartmentGroup group = departmentGroupService.getById(inventory.getGroupId());
            inventory.setDepartmentName(group.getName());
        }
        return Result.success(inventoryService.saveOrUpdate(inventory));
    }

    /**
     * 资产合并
     * @param dict
     * @return
     */
    @ApiOperation(value = "资产合并接口", notes = "资产合并接口")
    @RequestMapping(value = "inventoryMerge", method = RequestMethod.POST)
    @LoginValidate
    @OperLog(operModul="资产",operDesc="资产合并")
    public Result<Boolean> inventoryMerge(@RequestBody Dict dict) {

        String ids = dict.getStr("ids");
        String[] idsArray = ids.split(",");

        QueryWrapper<Inventory> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",Arrays.asList(idsArray));
        List<Inventory> inventoryList = inventoryService.list(queryWrapper);

        if(inventoryList.size() <= 1){
            throw new SystemException(CodeMsg.INVENTORY_MERGE_ERROR1);
        }

        List<String> hostNameList = CollUtil.getFieldValues(inventoryList,"hostname",String.class);
        List<Integer> idList = CollUtil.getFieldValues(inventoryList,"id",Integer.class);

        Set<String> hostNameSet = new HashSet<>(hostNameList);
        if(hostNameSet.size() != 1){
            throw new SystemException(CodeMsg.INVENTORY_MERGE_ERROR);
        }

        for(int i=1;i<idList.size();i++){
            idList.remove(i);
        }
        return Result.success(inventoryService.removeByIds(idList));
    }


    /**
     * 设置组织
     * @param dict
     * @return
     */
    @ApiOperation(value = "设置组织接口", notes = "设置组织接口")
    @RequestMapping(value = "setGroup", method = RequestMethod.POST)
    @LoginValidate
    @OperLog(operModul="资产",operDesc="设置组织")
    public Result<Boolean> setGroup(@RequestBody Dict dict) {

        Integer groupId = dict.getInt("groupId");
        String inventoryIds = dict.getStr("inventoryIds");
        String[] inventoryIdsArray = inventoryIds.split(",");

        //判断是否存在不可用的资产
        QueryWrapper<Inventory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_available","1");
        queryWrapper.in("id",Arrays.asList(inventoryIdsArray));
        List<Inventory> list = inventoryService.list(queryWrapper);
        if(list.size() != inventoryIdsArray.length){
            throw new SystemException(CodeMsg.INVENTORY_SETGROUP_ERROR);
        }

        //更新资产分组
        Inventory inventory = new Inventory();
        inventory.setGroupId(groupId);
        UpdateWrapper<Inventory> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("is_available","1");
        updateWrapper.in("id",Arrays.asList(inventoryIdsArray));

        DepartmentGroup departmentGroup = departmentGroupService.getById(groupId);
        inventory.setDepartmentName(departmentGroup.getName());

        return Result.success(inventoryService.update(inventory, updateWrapper));
    }

    /**
     * 设置测试接口
     * @param dict
     * @return
     */
    @ApiOperation(value = "设置测试接口（0未测试1已测试）", notes = "设置测试接口接口")
    @RequestMapping(value = "setTest", method = RequestMethod.POST)
    @OperLog(operModul="资产",operDesc="设置测试接口")
    public Result<Boolean> setTest(@RequestBody Dict dict) {
        String ids = dict.getStr("ids");
        String[] idsArray = ids.split(",");
        Inventory inventory = new Inventory();
        inventory.setIsTest(dict.getInt("isTest"));
        UpdateWrapper<Inventory> updateWrapper = new UpdateWrapper();
        updateWrapper.in("id",Arrays.asList(idsArray));
        return Result.success(inventoryService.update(inventory, updateWrapper));
    }

    /**
     * 设置标记接口
     * @param inventory
     * @return
     */
    @ApiOperation(value = "设置标记（0不可用1可用 2未配置 -1异常）", notes = "设置标记接口")
    @RequestMapping(value = "setAvailable", method = RequestMethod.POST)
    @OperLog(operModul="资产",operDesc="设置标记（0不可用1可用 2未配置 -1异常）")
    public Result<Boolean> setAvailable(@RequestBody Inventory inventory) {
        return Result.success(inventoryService.updateById(inventory));
    }

    /**
     * 删除资产
     * @param dict
     * @return
     */
    @ApiOperation(value = "删除资产接口", notes = "删除资产接口")
    @RequestMapping(value = "removeById", method = RequestMethod.POST)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Integer", paramType = "body"),
    })
    @LoginValidate
    @OperLog(operModul="资产",operDesc="删除资产接口")
    public Result<Boolean> removeById(@ApiIgnore @RequestBody Dict dict) {
        String id = dict.getStr("id");
        String[] ids = id.split(",");
        return Result.success(inventoryService.removeByIds( Arrays.asList(ids)));
    }
}
